﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface IPeriodoRepository : IRepository<Periodo>
    {
        Periodo FindLast();
        Periodo FindByPeriodo(string periodo);
        int GenerarPeriodo(Periodo _periodo);
        int RegistrarMensaje(PeriodoMensaje periodo_mensaje);
        IList<Periodo> GetPeriodosByIdCupon(int cupon_id);
        string FindMensajeMasivoPeriodo(int periodo_id);
        int VerificarMensajePeriodo(int periodo_id);
    }

    public class PeriodoRepository : IPeriodoRepository
    {
        protected readonly IDbConnection _db;

        public PeriodoRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        //public IList<AdicionalPlan> FindAdicionalesByPlan(int plan_id)
        //{
        //    throw new NotImplementedException();
        //}

        public IList<Periodo> FindAll()
        {
            string query = "SELECT * FROM PERIODOS ORDER BY FECHA_GENERACION DESC";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Periodo>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Periodo> Find(System.Linq.Expressions.Expression<Func<Periodo, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Periodo FindById(int id)
        {
            string query = "SELECT * FROM PERIODOS WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Periodo>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public Periodo FindLast()
        {
            string query = "SELECT * FROM PERIODOS ORDER BY ID DESC LIMIT 1";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Periodo>(query).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public Periodo FindByPeriodo(string periodo)
        {
            string query = "select * from periodos where DATE_FORMAT(periodo, '%m/%Y') = '" + periodo + "';";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Periodo>(query).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Add(Periodo newEntity)
        {
            string query = "INSERT INTO PERIODOS (PERIODO, FECHA_GENERACION, VENCIMIENTO_1, VENCIMIENTO_2, RECARGO) " +
                            "VALUES (@periodo, @fecha, @vencimiento1, @vencimiento2, @recargo); " +
                            "SELECT LAST_INSERT_ID();";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        periodo = newEntity.periodo,
                        fecha = newEntity.fecha_generacion,
                        vencimiento1 = newEntity.vencimiento_1,
                        vencimiento2 = newEntity.vencimiento_2,
                        recargo = newEntity.recargo
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            throw new NotImplementedException();
        }

        public int Modify(Periodo entity)
        {
            throw new NotImplementedException();
        }

        public int GenerarPeriodo(Periodo _periodo)
        {
            int generacion = 0;

            Datos.Repositories.SocioRepository socioRepository = new SocioRepository();
            Datos.Repositories.AdherenteRepository adherenteRepository = new AdherenteRepository();
            Datos.Repositories.PeriodoSocioRepository periodoSocioRepository = new PeriodoSocioRepository();

            IList<Socio> sociosL;
            sociosL = socioRepository.FindAll().Where(socios => socios.activo == 1).ToList();

            double cuota;

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    _db.Open();
                    using (var tran = _db.BeginTransaction())
                    {
                        try
                        {
                            int resultado = Add(_periodo);

                            if (resultado != 0)
                            {
                                bool res = true;

                                int idPeriodo = FindLast().id;

                                foreach (var socio in sociosL)
                                {
                                    cuota = new double();

                                    //buscar adherentes por socio
                                    socio.adherentes = adherenteRepository.FindByIdSocioActivos(socio.id);

                                    //calcular importe de la cuota por socio
                                    if(Convert.ToBoolean(socio.cuotafija) == true)
                                        cuota = ((socio.cuota + socio.recargo) - socio.bonificacion);
                                    else
                                        cuota = periodoSocioRepository.CalcularCuota(socio);

                                    //generar periodos por socio
                                    PeriodoSocio _periodosocio = new PeriodoSocio();
                                    _periodosocio.periodo_id = idPeriodo;
                                    _periodosocio.socio_id = socio.id;
                                    _periodosocio.importe = cuota;
                                    _periodosocio.estado = "I";

                                    if (periodoSocioRepository.Add(_periodosocio) == 0)
                                    {
                                        res = false;
                                        break;
                                    }
                                }

                                if (res == true)
                                {
                                    tran.Commit();

                                    generacion = 1;
                                }
                                else
                                {
                                    tran.Rollback();

                                    generacion = 0;
                                }
                            }
                        }
                        catch
                        {
                            tran.Rollback();

                            generacion = 0;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                throw e;
            }

            return generacion;
        }


        public IList<Periodo> GetPeriodosByIdCupon(int cupon_id)
        {
            string query = "SELECT PERIODOS.ID, PERIODOS.PERIODO, PERIODOS.FECHA_GENERACION, PERIODOS.VENCIMIENTO_1, PERIODOS.VENCIMIENTO_2, " +
                            "PERIODOS.RECARGO FROM CUPONESDETALLES " +
                            "INNER JOIN CUPONES ON CUPONES.ID = CUPONESDETALLES.CUPON_ID " +
                            "INNER JOIN PERIODOSSOCIOS ON PERIODOSSOCIOS.ID = CUPONESDETALLES.periodosocio_id " +
                            "INNER JOIN PERIODOS ON PERIODOS.ID = PERIODOSSOCIOS.PERIODO_ID " +
                            "WHERE CUPONES.ID = @cupon_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Periodo>(query, new { cupon_id = cupon_id }).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public int RegistrarMensaje(PeriodoMensaje periodo_mensaje)
        {
            const string query = "INSERT INTO PERIODOSMENSAJES (PERIODO_ID, MENSAJE) " +
                "VALUES (@periodo_id, @mensaje)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        periodo_id = periodo_mensaje.periodo_id,
                        mensaje = periodo_mensaje.mensaje
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public string FindMensajeMasivoPeriodo(int periodo_id)
        {
            const string query = "SELECT MENSAJE FROM PERIODOSMENSAJES " +
                "WHERE PERIODO_ID = @periodo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<string>(query, new { periodo_id = periodo_id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public int VerificarMensajePeriodo(int periodo_id)
        {
            const string query = "SELECT COUNT(*) FROM PERIODOSMENSAJES " +
                "WHERE PERIODO_ID = @periodo_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<int>(query, new { periodo_id = periodo_id }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }
    }
}
